#pragma once
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <vector>

const int Default_cap=10;


// template<class T>
// class RingQueue
// {

//     public:
//     RingQueue(int cap=Default_cap)
//     : _ringqueue(cap), _cap(cap),_Product_index(0),_Consume_index(0)
//     {
//         sem_init(&_Room_sem,0,cap);
//         sem_init(&_Data_sem,0,0);
//         pthread_mutex_init(&_Product_mutex,nullptr);
//         pthread_mutex_init(&_Consume_mutex,nullptr);
//     }


//     void Equeue(const T& x)
//     {
//         sem_wait(&_Room_sem);
//         pthread_mutex_lock(&_Product_mutex);
//         _ringqueue[_Product_index++]=x;
//         _Product_index%=_cap;
//         pthread_mutex_unlock(&_Product_mutex);
//         sem_post(&_Data_sem);
//     }

//     void Pop(T& x)
//     {
//         sem_wait(&_Data_sem);
//         pthread_mutex_lock(&_Consume_mutex);
//         x=_ringqueue[_Consume_index++];
//         _Consume_index%=_cap;
//         pthread_mutex_unlock(&_Consume_mutex);
//         sem_post(&_Room_sem);
//     }

//     ~RingQueue()
//     {
//         sem_destroy(&_Room_sem);
//         sem_destroy(&_Data_sem);
//         pthread_mutex_destroy(&_Product_mutex);
//         pthread_mutex_destroy(&_Consume_mutex);
//     }


//     private:
//     // 数组模拟环形队列
//     std::vector<T> _ringqueue;
//     //队列容量
//     int _cap;

//     int _Product_index;      // 生产者下标
//     int _Consume_index;      // 消费者下标

//     // 信号量
//     sem_t _Room_sem;
//     sem_t _Data_sem;
//     //锁
//     pthread_mutex_t _Product_mutex;
//     pthread_mutex_t _Consume_mutex;
// };

#include "Sem.hpp"
#include "Mutex.hpp"

using namespace MutexMoudle;


template<class T>
class RingQueue
{

    public:
    RingQueue(int cap=Default_cap)
    : _ringqueue(cap), _cap(cap),_Product_index(0),_Consume_index(0),_Room_sem(cap),_Data_sem(0)
    {}


    void Equeue(const T& x)
    {
        _Room_sem.P();
 //       {
            LockGuard  lock(_Product_mutex); 
            _ringqueue[_Product_index++]=x;
            _Product_index%=_cap;
 //       }
        _Data_sem.V();
    }

    void Pop(T& x)
    {
        _Data_sem.P();
        LockGuard lock(_Consume_mutex); 
        x=_ringqueue[_Consume_index++];
        _Consume_index%=_cap;
        _Room_sem.V();
    }
    
    ~RingQueue()
    {}


    private:
    // 数组模拟环形队列
    std::vector<T> _ringqueue;
    //队列容量
    int _cap;

    int _Product_index;      // 生产者下标
    int _Consume_index;      // 消费者下标

    // 信号量
    Sem _Room_sem;
    Sem _Data_sem;
    //锁
    Mutex _Product_mutex;
    Mutex _Consume_mutex;
};